<template>
  <!-- 自定义标签形式创建的组件，父组件向子组件传值会作用在标签属性上
    故对于引用类型，需调用 JSON.stringify 转换 -->
  <my-div :obj="JSON.stringify(obj)" :num="20"></my-div>
</template>
<script setup lang="ts">
// 导入子组件
import cusEle from './CustomElement.ce.vue'
// 导入封装定义自定义标签的方法
import { defineCustomElement } from 'vue'

// js 原生封装组件实现复用
// 采用自定义元素标签 CustomElement 形式
// 调用该方法，第一个参数为注册的自定义元素标签名，第二个为以类形式创建的组件
// window.customElements.define(string,class)
// 组件创建以类的形式，该类继承自HTMLElement
// class Component extends HTMLElement {constructor(){super()} h(){} callback(){}}
// 在组件的类的构造函数中创建 UI 结构并挂载到影子 DOM ，且组件可以定义生命周期回调，定义渲染器函数h
// 影子 DOM ：用于隔离组件的样式
// 在构造函数中掉 this.attatchShadow({mode:"open"}) 创建影子 DOM
// 对影子 DOM 调用 appendChild 添加组件的 UI 结构
// UI 结构的创建可以采用 js 操作创建 DOM 形式
// 采用 template 模板形式，先创建模板再在 template.innerHTML 中写 html
// 采用模板形式时，需要调用 template.content.cloneNode(true) 复制模板节点再添加到影子 DOM 中

// 在 vue 中使用自定义标签元素的形式创建组件
// 在 vite 中对 vue 进行配置，使其对包含特定字符的标签识别为自定义标签
// vue 对根据 .ce.vue 文件创建自定义元素组件进行封装
// defineCustomElement(.ce.vue) 返回值为以类形式创建的组件，即将 .ce.vue 转化为自定义标签的类的形式
// 调用 window.customElements.define(string,class) 注册使用，需与配置时的特定字符一致

// 注意：在自定义标签组件使用时，父组件向子组件传递值时，传递到子组件的元素属性上
// 故当值为引用类型时，需要在父组件中调用 JSON.stringify 进行转化，才能在子组件读值



// 将组件以自定义标签的形式创建
const Div = defineCustomElement(cusEle)
// 将自定义标签以特定名注册以供模板使用
window.customElements.define('my-div', Div)
const obj = reactive({
  name: 'Tom',
  age: 20,
})
</script>
<style scoped lang="less"></style>
